﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using MongoDB.Driver;
using MongoDB.Bson;
using System.Collections;
using System.Net;
using Silmoon.Threading;
using System.Threading;

namespace Silmoon.DNS.Monitoring
{
    public class MonitorCollectController : Silmoon.MySilmoon.RunningAble
    {
        public event MonitorResultHandler OnResultCompleted;
        GBC g = null;
        ArrayList Monitors = new ArrayList();
        long MonitorSN = 0;
        public MonitorCollectController(GBC g)
        {
            this.g = g;
            this.OnStart += new OperateHandler(MonitorCollectController_OnStart);
            this.OnStop += new OperateHandler(MonitorCollectController_OnStop);
        }

        void InitMonitors()
        {
            IsChange();
            MongoCollection collection = g.mongo.GetMonitorListCollection();
            MongoCursor<BsonDocument> cursor = collection.FindAllAs<BsonDocument>();
            DisposeAllMonitor();
            Monitors.Clear();
            foreach (BsonDocument document in cursor)
            {
                string host = document["fqdn"].ToString();
                if (host[host.Length - 1] == char.Parse("."))
                    host = host.Substring(0, host.Length -1);

                Monitor monitor = new Monitor(g);
                MonitorInfo info = new MonitorInfo();
                info.Address = IPAddress.Parse(document["ip"].ToString());
                info.Host = host;
                info.Param = document["param"].ToString();
                info.Port = document["port"].AsInt32;
                info.Type = (MONITOR_TYPE)document["type"].AsInt32;
                info.RecordOId = document["recordoid"].AsObjectId;

                monitor.Info = info;
                monitor.Start();
                Monitors.Add(monitor);
            }
        }

        bool IsChange()
        {
            MongoCollection collection = g.mongo.GetMongoDatabase().GetCollection("monitorinfo");
            MongoCursor<BsonDocument> cursor = collection.FindAllAs<BsonDocument>();
            foreach (BsonDocument document in cursor)
            {
                long l = document["sn"].AsInt64;
                bool change = false;
                change = (l != MonitorSN);
                MonitorSN = l;
                return change;
            }
            return false;
        }
        void DisposeAllMonitor()
        {
            foreach (Monitor monitor in Monitors)
            {
                monitor.Dispose();
            }
        }
        void CloseAllMonitor()
        {
            foreach (Monitor monitor in Monitors)
            {
                monitor.Abort();
            }
        }

        void NewThreadStartCycle()
        {
            while (RunningState == MySilmoon.RunningState.Running)
            {
                if (IsChange())
                {
                    g.onOutputText("monitor info changed.", 1);
                    InitMonitors();
                }

                foreach (Monitor monitor in Monitors)
                {
                    monitor.CheckOnce();
                }
                g.onOutputText("new cycle thread is comleted.");

                Thread.Sleep(g.configure.monitor_timespan);
                CloseAllMonitor();
            }
        }

        bool MonitorCollectController_OnStart(bool success)
        {
            InitMonitors();
            g.onOutputText("load monitors completed.");
            Threads.ExecAsync(NewThreadStartCycle, g.onThreadException);
            g.onOutputText("monitors has been started.");
            return true;
        }
        bool MonitorCollectController_OnStop(bool success)
        {
            return true;
        }

        public void onResultCompleted(MonitorResult result)
        {
            g.communicator.AsyncNotifySimpleState(result);
            if (OnResultCompleted != null) OnResultCompleted(result);
        }
    }
    public delegate void MonitorResultHandler(MonitorResult result);
}
